forked from buildpacks/lifecycle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
149 lines (131 loc) · 3.44 KB
/
utils.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
package lifecycle
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"github.com/BurntSushi/toml"
"github.com/buildpacks/imgutil"
"github.com/pkg/errors"
"github.com/buildpacks/lifecycle/buildpack"
)
func WriteTOML(path string, data interface{}) error {
if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
return err
}
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
return toml.NewEncoder(f).Encode(data)
}
func ReadGroup(path string) (buildpack.Group, error) {
var group buildpack.Group
_, err := toml.DecodeFile(path, &group)
return group, err
}
func ReadOrder(path string) (buildpack.Order, error) {
var order struct {
Order buildpack.Order `toml:"order"`
}
_, err := toml.DecodeFile(path, &order)
return order.Order, err
}
func TruncateSha(sha string) string {
rawSha := strings.TrimPrefix(sha, "sha256:")
if len(sha) > 12 {
return rawSha[0:12]
}
return rawSha
}
func DecodeLabel(image imgutil.Image, label string, v interface{}) error {
if !image.Found() {
return nil
}
contents, err := image.Label(label)
if err != nil {
return errors.Wrapf(err, "retrieving label '%s' for image '%s'", label, image.Name())
}
if contents == "" {
return nil
}
if err := json.Unmarshal([]byte(contents), v); err != nil {
return errors.Wrapf(err, "failed to unmarshal context of label '%s'", label)
}
return nil
}
func removeStagePrefixes(mixins []string) []string {
var result []string
for _, m := range mixins {
s := strings.SplitN(m, ":", 2)
if len(s) == 1 {
result = append(result, s[0])
} else {
result = append(result, s[1])
}
}
return result
}
// compare performs a set comparison between two slices. `extra` represents elements present in
// `strings1` but not `strings2`. `missing` represents elements present in `strings2` that are
// missing from `strings1`. `common` represents elements present in both slices. Since the input
// slices are treated as sets, duplicates will be removed in any outputs.
// from: https://github.com/buildpacks/pack/blob/main/internal/stringset/stringset.go
func compare(strings1, strings2 []string) (extra []string, missing []string, common []string) {
set1 := map[string]struct{}{}
set2 := map[string]struct{}{}
for _, s := range strings1 {
set1[s] = struct{}{}
}
for _, s := range strings2 {
set2[s] = struct{}{}
}
for s := range set1 {
if _, ok := set2[s]; !ok {
extra = append(extra, s)
continue
}
common = append(common, s)
}
for s := range set2 {
if _, ok := set1[s]; !ok {
missing = append(missing, s)
}
}
return extra, missing, common
}
func syncLabels(sourceImg imgutil.Image, destImage imgutil.Image, test func(string) bool) error {
if err := removeLabels(destImage, test); err != nil {
return err
}
return copyLabels(sourceImg, destImage, test)
}
func removeLabels(image imgutil.Image, test func(string) bool) error {
labels, err := image.Labels()
if err != nil {
return err
}
for label := range labels {
if test(label) {
if err := image.RemoveLabel(label); err != nil {
return errors.Wrapf(err, "failed to remove label '%s'", label)
}
}
}
return nil
}
func copyLabels(fromImage imgutil.Image, destImage imgutil.Image, test func(string) bool) error {
fromLabels, err := fromImage.Labels()
if err != nil {
return err
}
for label, labelValue := range fromLabels {
if test(label) {
if err := destImage.SetLabel(label, labelValue); err != nil {
return err
}
}
}
return nil
}