Skip to content

Commit 75c8e7b

Browse files
committed
Fix whitespace handling in control files
1 parent 1923f5c commit 75c8e7b

File tree

2 files changed

+100
-8
lines changed

2 files changed

+100
-8
lines changed

internal/deb/control.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,15 @@ func (p *Parser) Next() bool {
177177
return false
178178

179179
}
180-
field.Value = strings.TrimSpace(text[colon+1 : valueEnd])
180+
field.Value = text[colon+1 : valueEnd]
181181
case Folded:
182-
field.Value = strings.ReplaceAll(strings.TrimSpace(text[colon+1:valueEnd]), "\n", "")
182+
field.Value = strings.ReplaceAll(text[colon+1:valueEnd], "\n", "")
183183
case Multiline:
184184
field.Value = text[colon+1 : valueEnd]
185185
default:
186186
panic("unknown field type")
187187
}
188+
field.Value = strings.Trim(field.Value, " \t")
188189
if field.Value == "" {
189190
p.clear()
190191
p.err = fmt.Errorf("parse debian control file: line %d: empty field %q", startLine, field.Name)
@@ -262,10 +263,15 @@ func (f Field) write(w io.Writer) error {
262263
if _, err := io.WriteString(w, f.Name); err != nil {
263264
return err
264265
}
265-
if _, err := w.Write(fieldSep); err != nil {
266+
val := strings.Trim(f.Value, " \t")
267+
sepN := len(fieldSep)
268+
if strings.HasPrefix(val, "\n") {
269+
sepN = 1
270+
}
271+
if _, err := w.Write(fieldSep[:sepN]); err != nil {
266272
return err
267273
}
268-
if _, err := io.WriteString(w, f.Value); err != nil {
274+
if _, err := io.WriteString(w, val); err != nil {
269275
return err
270276
}
271277
return nil

internal/deb/control_test.go

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ func TestParser(t *testing.T) {
3636
},
3737
{
3838
name: "SingleField",
39-
source: "Package: libc6\n",
39+
source: "Package:libc6\n",
4040
want: []Paragraph{
4141
{{Name: "Package", Value: "libc6"}},
4242
},
4343
},
44+
{
45+
name: "Whitespace",
46+
source: "Version: \t libc6 (= 6.1) \t \n",
47+
want: []Paragraph{
48+
{{Name: "Version", Value: "libc6 (= 6.1)"}},
49+
},
50+
},
4451
{
4552
name: "MissingLF",
4653
source: "Package: libc6",
@@ -91,15 +98,15 @@ func TestParser(t *testing.T) {
9198
source: "Description: Hello World\n",
9299
fields: map[string]FieldType{"Description": Multiline},
93100
want: []Paragraph{
94-
{{Name: "Description", Value: " Hello World"}},
101+
{{Name: "Description", Value: "Hello World"}},
95102
},
96103
},
97104
{
98105
name: "MultilineField/MultipleLines",
99106
source: "Description: Hello World\n Extended description\n",
100107
fields: map[string]FieldType{"Description": Multiline},
101108
want: []Paragraph{
102-
{{Name: "Description", Value: " Hello World\n Extended description"}},
109+
{{Name: "Description", Value: "Hello World\n Extended description"}},
103110
},
104111
},
105112
{
@@ -115,7 +122,7 @@ func TestParser(t *testing.T) {
115122
source: "Description: \n Extended description\n",
116123
fields: map[string]FieldType{"Description": Multiline},
117124
want: []Paragraph{
118-
{{Name: "Description", Value: " \n Extended description"}},
125+
{{Name: "Description", Value: "\n Extended description"}},
119126
},
120127
},
121128

@@ -211,3 +218,82 @@ func TestParser(t *testing.T) {
211218
}
212219
})
213220
}
221+
222+
func TestSave(t *testing.T) {
223+
tests := []struct {
224+
name string
225+
paragraphs []Paragraph
226+
want string
227+
}{
228+
{
229+
name: "Empty",
230+
want: "",
231+
},
232+
{
233+
name: "SingleField",
234+
paragraphs: []Paragraph{
235+
{
236+
{"Package", "libc6"},
237+
},
238+
},
239+
want: "Package: libc6\n",
240+
},
241+
{
242+
name: "Whitespace",
243+
paragraphs: []Paragraph{
244+
{
245+
{"Version", " \t libc6 (= 6.1) \t "},
246+
},
247+
},
248+
want: "Version: libc6 (= 6.1)\n",
249+
},
250+
{
251+
name: "TwoFields",
252+
paragraphs: []Paragraph{
253+
{
254+
{"Package", "libc6"},
255+
{"Version", "1:6.2"},
256+
},
257+
},
258+
want: "Package: libc6\nVersion: 1:6.2\n",
259+
},
260+
{
261+
name: "Multiline/WithFirst",
262+
paragraphs: []Paragraph{
263+
{
264+
{"Description", "Do nothing\n Totally here just to do nothing"},
265+
},
266+
},
267+
want: "Description: Do nothing\n Totally here just to do nothing\n",
268+
},
269+
{
270+
name: "Multiline/WithoutFirst",
271+
paragraphs: []Paragraph{
272+
{
273+
{"Description", "\n Totally here just to do nothing"},
274+
},
275+
},
276+
want: "Description:\n Totally here just to do nothing\n",
277+
},
278+
{
279+
name: "Multiline/FirstLineWhitespace",
280+
paragraphs: []Paragraph{
281+
{
282+
{"Description", " \t \n Totally here just to do nothing"},
283+
},
284+
},
285+
want: "Description:\n Totally here just to do nothing\n",
286+
},
287+
}
288+
for _, test := range tests {
289+
t.Run(test.name, func(t *testing.T) {
290+
got := new(strings.Builder)
291+
if err := Save(got, test.paragraphs); err != nil {
292+
t.Error("Save:", err)
293+
}
294+
if diff := cmp.Diff(test.want, got.String()); diff != "" {
295+
t.Errorf("Output (-want +got):\n%s", diff)
296+
}
297+
})
298+
}
299+
}

0 commit comments

Comments
 (0)