...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package layout
17
18 import (
19 "fmt"
20 "io/fs"
21 "path/filepath"
22 "strings"
23
24 v1 "github.com/google/go-containerregistry/pkg/v1"
25 )
26
27
28
29
30
31
32 func (l Path) GarbageCollect() ([]v1.Hash, error) {
33 idx, err := l.ImageIndex()
34 if err != nil {
35 return nil, err
36 }
37 blobsToKeep := map[string]bool{}
38 if err := l.garbageCollectImageIndex(idx, blobsToKeep); err != nil {
39 return nil, err
40 }
41 blobsDir := l.path("blobs")
42 removedBlobs := []v1.Hash{}
43
44 err = filepath.WalkDir(blobsDir, func(path string, d fs.DirEntry, err error) error {
45 if err != nil {
46 return err
47 }
48
49 if d.IsDir() {
50 return nil
51 }
52
53 rel, err := filepath.Rel(blobsDir, path)
54 if err != nil {
55 return err
56 }
57 hashString := strings.Replace(rel, "/", ":", 1)
58 if present := blobsToKeep[hashString]; !present {
59 h, err := v1.NewHash(hashString)
60 if err != nil {
61 return err
62 }
63 removedBlobs = append(removedBlobs, h)
64 }
65 return nil
66 })
67
68 if err != nil {
69 return nil, err
70 }
71
72 return removedBlobs, nil
73 }
74
75 func (l Path) garbageCollectImageIndex(index v1.ImageIndex, blobsToKeep map[string]bool) error {
76 idxm, err := index.IndexManifest()
77 if err != nil {
78 return err
79 }
80
81 h, err := index.Digest()
82 if err != nil {
83 return err
84 }
85
86 blobsToKeep[h.String()] = true
87
88 for _, descriptor := range idxm.Manifests {
89 if descriptor.MediaType.IsImage() {
90 img, err := index.Image(descriptor.Digest)
91 if err != nil {
92 return err
93 }
94 if err := l.garbageCollectImage(img, blobsToKeep); err != nil {
95 return err
96 }
97 } else if descriptor.MediaType.IsIndex() {
98 idx, err := index.ImageIndex(descriptor.Digest)
99 if err != nil {
100 return err
101 }
102 if err := l.garbageCollectImageIndex(idx, blobsToKeep); err != nil {
103 return err
104 }
105 } else {
106 return fmt.Errorf("gc: unknown media type: %s", descriptor.MediaType)
107 }
108 }
109 return nil
110 }
111
112 func (l Path) garbageCollectImage(image v1.Image, blobsToKeep map[string]bool) error {
113 h, err := image.Digest()
114 if err != nil {
115 return err
116 }
117 blobsToKeep[h.String()] = true
118
119 h, err = image.ConfigName()
120 if err != nil {
121 return err
122 }
123 blobsToKeep[h.String()] = true
124
125 ls, err := image.Layers()
126 if err != nil {
127 return err
128 }
129 for _, l := range ls {
130 h, err := l.Digest()
131 if err != nil {
132 return err
133 }
134 blobsToKeep[h.String()] = true
135 }
136 return nil
137 }
138
View as plain text