-
Notifications
You must be signed in to change notification settings - Fork 111
/
Copy pathfactory.go
102 lines (91 loc) · 2.51 KB
/
factory.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
package layers
import (
"os"
"path/filepath"
"strings"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/buildpacks/lifecycle/archive"
"github.com/buildpacks/lifecycle/log"
)
const (
AppLayerName = "Application Layer"
BuildpackLayerName = "Layer: '%s', Created by buildpack: %s"
ExtensionLayerName = "Layer: '%s', Created by extension: %s"
LauncherConfigLayerName = "Buildpacks Launcher Config"
LauncherLayerName = "Buildpacks Application Launcher"
ProcessTypesLayerName = "Buildpacks Process Types"
SBOMLayerName = "Software Bill-of-Materials"
SliceLayerName = "Application Slice: %d"
)
type Factory struct {
ArtifactsDir string // ArtifactsDir is the directory where layer files are written
UID, GID int // UID and GID are used to normalize layer entries
Logger log.Logger
tarHashes map[string]string // tarHases Stores hashes of layer tarballs for reuse between the export and cache steps.
}
type Layer struct {
ID string
TarPath string
Digest string
History v1.History
}
func (f *Factory) writeLayer(id, createdBy string, addEntries func(tw *archive.NormalizingTarWriter) error) (layer Layer, err error) {
tarPath := filepath.Join(f.ArtifactsDir, escape(id)+".tar")
if f.tarHashes == nil {
f.tarHashes = make(map[string]string)
}
if sha, ok := f.tarHashes[tarPath]; ok {
f.Logger.Debugf("Reusing tarball for layer %q with SHA: %s\n", id, sha)
return Layer{
ID: id,
TarPath: tarPath,
Digest: sha,
History: v1.History{CreatedBy: createdBy},
}, nil
}
lw, err := newFileLayerWriter(tarPath)
if err != nil {
return Layer{}, err
}
defer func() {
if closeErr := lw.Close(); err == nil {
err = closeErr
}
}()
tw := tarWriter(lw)
if err := addEntries(tw); err != nil {
return Layer{}, err
}
if err := tw.Close(); err != nil {
return Layer{}, err
}
digest := lw.Digest()
f.tarHashes[tarPath] = digest
return Layer{
ID: id,
Digest: digest,
TarPath: tarPath,
History: v1.History{CreatedBy: createdBy},
}, err
}
func escape(id string) string {
return strings.ReplaceAll(id, "/", "_")
}
func parents(file string) ([]archive.PathInfo, error) {
parent := filepath.Dir(file)
if parent == filepath.VolumeName(file)+`\` || parent == "/" {
return []archive.PathInfo{}, nil
}
fi, err := os.Stat(parent)
if err != nil {
return nil, err
}
parentDirs, err := parents(parent)
if err != nil {
return nil, err
}
return append(parentDirs, archive.PathInfo{
Path: parent,
Info: fi,
}), nil
}