-
Notifications
You must be signed in to change notification settings - Fork 103
/
handle_toml.go
197 lines (176 loc) · 6.73 KB
/
handle_toml.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Package files contains schema and helper methods for working with lifecycle configuration files.
package files
import (
"fmt"
"os"
"github.com/BurntSushi/toml"
"github.com/buildpacks/lifecycle/api"
"github.com/buildpacks/lifecycle/buildpack"
"github.com/buildpacks/lifecycle/internal/encoding"
"github.com/buildpacks/lifecycle/log"
)
// Handler is the default handler used to read and write lifecycle configuration files.
var Handler = &TOMLHandler{}
// TOMLHandler reads and writes lifecycle configuration files in TOML format.
type TOMLHandler struct{}
// NewHandler returns a new file handler.
func NewHandler() *TOMLHandler {
return &TOMLHandler{}
}
// ReadAnalyzed reads the provided analyzed.toml file.
// It logs a warning and returns empty analyzed metadata if the file does not exist.
func (h *TOMLHandler) ReadAnalyzed(path string, logger log.Logger) (Analyzed, error) {
var analyzed Analyzed
if _, err := toml.DecodeFile(path, &analyzed); err != nil {
if os.IsNotExist(err) {
logger.Warnf("No analyzed metadata found at path %q", path)
return Analyzed{}, nil
}
return Analyzed{}, fmt.Errorf("failed to read analyzed file: %w", err)
}
return analyzed, nil
}
// WriteAnalyzed writes the provided analyzed metadata at the provided path.
func (h *TOMLHandler) WriteAnalyzed(path string, analyzedMD *Analyzed, logger log.Logger) error {
logger.Debugf("Run image info in analyzed metadata is: ")
logger.Debugf(encoding.ToJSONMaybe(analyzedMD.RunImage))
if err := encoding.WriteTOML(path, analyzedMD); err != nil {
return fmt.Errorf("failed to write analyzed file: %w", err)
}
return nil
}
// ReadGroup reads the provided group.toml file.
func (h *TOMLHandler) ReadGroup(path string) (group buildpack.Group, err error) {
if _, err = toml.DecodeFile(path, &group); err != nil {
return buildpack.Group{}, fmt.Errorf("failed to read group file: %w", err)
}
for e := range group.GroupExtensions {
group.GroupExtensions[e].Extension = true
group.GroupExtensions[e].Optional = true
}
return group, nil
}
// WriteGroup writes the provided group information at the provided path.
func (h *TOMLHandler) WriteGroup(path string, group *buildpack.Group) error {
for e := range group.GroupExtensions {
group.GroupExtensions[e].Extension = false
group.GroupExtensions[e].Optional = false // avoid printing redundant information (extensions are always optional)
}
if err := encoding.WriteTOML(path, group); err != nil {
return fmt.Errorf("failed to write group file: %w", err)
}
return nil
}
// ReadBuildMetadata reads the provided metadata.toml file,
// and sets the provided Platform API version on the returned struct so that the data can be re-encoded properly later.
func (h *TOMLHandler) ReadBuildMetadata(path string, platformAPI *api.Version) (*BuildMetadata, error) {
buildMD := BuildMetadata{}
_, err := toml.DecodeFile(path, &buildMD)
if err != nil {
return nil, fmt.Errorf("failed to read build metadata file: %w", err)
}
buildMD.PlatformAPI = platformAPI
for i, process := range buildMD.Processes {
buildMD.Processes[i] = process.WithPlatformAPI(platformAPI)
}
return &buildMD, nil
}
// WriteBuildMetadata writes the provided build metadata at the provided path.
func (h *TOMLHandler) WriteBuildMetadata(path string, buildMD *BuildMetadata) error {
if err := encoding.WriteTOML(path, buildMD); err != nil {
return fmt.Errorf("failed to write build metadata file: %w", err)
}
return nil
}
// ReadOrder reads the provided order.toml file.
func (h *TOMLHandler) ReadOrder(path string) (buildpack.Order, buildpack.Order, error) {
orderBp, orderExt, err := readOrder(path)
if err != nil {
return buildpack.Order{}, buildpack.Order{}, err
}
return orderBp, orderExt, nil
}
func readOrder(path string) (buildpack.Order, buildpack.Order, error) {
var order struct {
Order buildpack.Order `toml:"order"`
OrderExtensions buildpack.Order `toml:"order-extensions"`
}
_, err := toml.DecodeFile(path, &order)
if err != nil {
return nil, nil, fmt.Errorf("failed to read order file: %w", err)
}
for g, group := range order.OrderExtensions {
for e := range group.Group {
group.Group[e].Extension = true
group.Group[e].Optional = true
}
order.OrderExtensions[g] = group
}
return order.Order, order.OrderExtensions, nil
}
// ReadPlan reads the provided plan.toml file.
func (h *TOMLHandler) ReadPlan(path string) (Plan, error) {
var plan Plan
if _, err := toml.DecodeFile(path, &plan); err != nil {
return Plan{}, fmt.Errorf("failed to read plan file: %w", err)
}
return plan, nil
}
// WritePlan writes the provided plan information at the provided path.
func (h *TOMLHandler) WritePlan(path string, plan *Plan) error {
if err := encoding.WriteTOML(path, plan); err != nil {
return fmt.Errorf("failed to write plan file: %w", err)
}
return nil
}
// ReadProjectMetadata reads the provided project_metadata.toml file.
// It logs a warning and returns empty project metadata if the file does not exist.
func (h *TOMLHandler) ReadProjectMetadata(path string, logger log.Logger) (ProjectMetadata, error) {
var projectMD ProjectMetadata
if _, err := toml.DecodeFile(path, &projectMD); err != nil {
if os.IsNotExist(err) {
logger.Debugf("No project metadata found at path %q, project metadata will not be exported", path)
return ProjectMetadata{}, nil
}
return ProjectMetadata{}, fmt.Errorf("failed to read project metadata file: %w", err)
}
return projectMD, nil
}
// WriteReport writes the provided report information at the provided path.
func (h *TOMLHandler) WriteReport(path string, report *Report) error {
if err := encoding.WriteTOML(path, report); err != nil {
return fmt.Errorf("failed to write report file: %w", err)
}
return nil
}
// WriteRebaseReport writes the provided report information at the provided path.
func (h *TOMLHandler) WriteRebaseReport(path string, report *RebaseReport) error {
if err := encoding.WriteTOML(path, report); err != nil {
return fmt.Errorf("failed to write report file: %w", err)
}
return nil
}
// ReadRun reads the provided run.toml file.
func (h *TOMLHandler) ReadRun(path string, logger log.Logger) (Run, error) {
var runMD Run
if _, err := toml.DecodeFile(path, &runMD); err != nil {
if os.IsNotExist(err) {
logger.Infof("No run metadata found at path %q", path)
return Run{}, nil
}
return Run{}, fmt.Errorf("failed to read run file: %w", err)
}
return runMD, nil
}
// ReadStack reads the provided stack.toml file.
func (h *TOMLHandler) ReadStack(path string, logger log.Logger) (Stack, error) {
var stackMD Stack
if _, err := toml.DecodeFile(path, &stackMD); err != nil {
if os.IsNotExist(err) {
logger.Infof("No stack metadata found at path %q", path)
return Stack{}, nil
}
return Stack{}, fmt.Errorf("failed to read stack file: %w", err)
}
return stackMD, nil
}