Skip to content

Commit

Permalink
unit: stable serialization order
Browse files Browse the repository at this point in the history
6654289 introduced consolidation of
UnitOptions into Sections during serialization. This preserved ordering
of individual options within sections, but since a map was used to house
the sections their order was nondeterministic.

This change moves to preserving the first-seen order of the sections, as
well as continuing to preserve the order of units with sections. For
example:

	[UnitOption{A, B, b}, UnitOption{C, D, d}, UnitOption{A, Z, z}]

will consistently be written as:

	[A]
	B=b
	Z=z
	[C]
	D=d
  • Loading branch information
jonboulle committed Jun 29, 2015
1 parent 9b2f329 commit 3130945
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
24 changes: 18 additions & 6 deletions unit/serialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,40 @@ import (
"io"
)

// Serialize encodes all of the given UnitOption objects into a unit file
// Serialize encodes all of the given UnitOption objects into a
// unit file. When serialized the options are sorted in their
// supplied order but grouped by section.
func Serialize(opts []*UnitOption) io.Reader {
var buf bytes.Buffer

if len(opts) == 0 {
return &buf
}

// Index of sections -> ordered options
idx := map[string][]*UnitOption{}
// Separately preserve order in which sections were seen
sections := []string{}
for _, opt := range opts {
idx[opt.Section] = append(idx[opt.Section], opt)
sec := opt.Section
if _, ok := idx[sec]; !ok {
sections = append(sections, sec)
}
idx[sec] = append(idx[sec], opt)
}

for curSection, curOpts := range idx {
writeSectionHeader(&buf, curSection)
for i, sect := range sections {
writeSectionHeader(&buf, sect)
writeNewline(&buf)

for _, opt := range curOpts {
opts := idx[sect]
for _, opt := range opts {
writeOption(&buf, opt)
writeNewline(&buf)
}
writeNewline(&buf)
if i < len(sections)-1 {
writeNewline(&buf)
}
}

return &buf
Expand Down
28 changes: 25 additions & 3 deletions unit/serialize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ ExecStart=/usr/bin/sleep infinity
`,
},

// no optimization for unsorted options
// options are grouped into sections
{
[]*UnitOption{
&UnitOption{"Unit", "Description", "Foo"},
Expand All @@ -77,12 +77,34 @@ ExecStart=/usr/bin/sleep infinity
},
`[Unit]
Description=Foo
BindsTo=bar.service
[Service]
ExecStart=/usr/bin/sleep infinity
`,
},

[Unit]
// options are ordered within groups, and sections are ordered in the order in which they were first seen
{
[]*UnitOption{
&UnitOption{"Unit", "Description", "Foo"},
&UnitOption{"Service", "ExecStart", "/usr/bin/sleep infinity"},
&UnitOption{"Unit", "BindsTo", "bar.service"},
&UnitOption{"X-Foo", "Bar", "baz"},
&UnitOption{"Service", "ExecStop", "/usr/bin/sleep 1"},
&UnitOption{"Unit", "Documentation", "https://foo.com"},
},
`[Unit]
Description=Foo
BindsTo=bar.service
Documentation=https://foo.com
[Service]
ExecStart=/usr/bin/sleep infinity
ExecStop=/usr/bin/sleep 1
[X-Foo]
Bar=baz
`,
},

Expand Down Expand Up @@ -140,7 +162,7 @@ o

output := string(outBytes)
if tt.output != output {
t.Errorf("case %d: incorrect output")
t.Errorf("case %d: incorrect output", i)
t.Logf("Expected:\n%s", tt.output)
t.Logf("Actual:\n%s", output)
}
Expand Down

0 comments on commit 3130945

Please sign in to comment.