6
6
"fmt"
7
7
"io/fs"
8
8
"path/filepath"
9
+ "slices"
9
10
"strings"
10
11
11
12
intoto "github.com/in-toto/in-toto-golang/in_toto"
@@ -63,6 +64,7 @@ func supplementSBOM(ctx context.Context, s session.Group, target cache.Immutable
63
64
if err != nil {
64
65
return att , err
65
66
}
67
+ defer layers .release (context .WithoutCancel (ctx ))
66
68
modifyFile := func (f * spdx.File ) error {
67
69
if f == nil {
68
70
// Skip over nil entries - this is likely a bug in the SPDX parser,
@@ -77,7 +79,7 @@ func supplementSBOM(ctx context.Context, s session.Group, target cache.Immutable
77
79
return nil
78
80
}
79
81
80
- _ , desc , err := layers .find (ctx , s , f .FileName )
82
+ desc , err := layers .find (ctx , s , f .FileName )
81
83
if err != nil {
82
84
if ! errors .Is (err , fs .ErrNotExist ) {
83
85
return err
@@ -144,13 +146,9 @@ func encodeSPDX(s *spdx.Document) (dt []byte, err error) {
144
146
// fileLayerFinder finds the layer that contains a file, with caching to avoid
145
147
// repeated FileList lookups.
146
148
type fileLayerFinder struct {
147
- pending []fileLayerEntry
148
- cache map [string ]fileLayerEntry
149
- }
150
-
151
- type fileLayerEntry struct {
152
- ref cache.ImmutableRef
153
- desc ocispecs.Descriptor
149
+ refs []cache.ImmutableRef
150
+ pending []ocispecs.Descriptor
151
+ cache map [string ]ocispecs.Descriptor
154
152
}
155
153
156
154
func newFileLayerFinder (target cache.ImmutableRef , remote * solver.Remote ) (fileLayerFinder , error ) {
@@ -159,14 +157,10 @@ func newFileLayerFinder(target cache.ImmutableRef, remote *solver.Remote) (fileL
159
157
if len (chain ) != len (descs ) {
160
158
return fileLayerFinder {}, errors .New ("layer chain and descriptor list are not the same length" )
161
159
}
162
-
163
- pending := make ([]fileLayerEntry , len (chain ))
164
- for i , ref := range chain {
165
- pending [i ] = fileLayerEntry {ref : ref , desc : descs [i ]}
166
- }
167
160
return fileLayerFinder {
168
- pending : pending ,
169
- cache : map [string ]fileLayerEntry {},
161
+ pending : slices .Clone (descs ),
162
+ refs : chain ,
163
+ cache : map [string ]ocispecs.Descriptor {},
170
164
}, nil
171
165
}
172
166
@@ -175,20 +169,21 @@ func newFileLayerFinder(target cache.ImmutableRef, remote *solver.Remote) (fileL
175
169
// the layer that created the file, not the one that deleted it.
176
170
//
177
171
// find is not concurrency-safe.
178
- func (c * fileLayerFinder ) find (ctx context.Context , s session.Group , filename string ) (cache. ImmutableRef , * ocispecs.Descriptor , error ) {
172
+ func (c * fileLayerFinder ) find (ctx context.Context , s session.Group , filename string ) (* ocispecs.Descriptor , error ) {
179
173
filename = filepath .Join ("/" , filename )
180
174
181
175
// return immediately if we've already found the layer containing filename
182
176
if cache , ok := c .cache [filename ]; ok {
183
- return cache . ref , & cache . desc , nil
177
+ return & cache , nil
184
178
}
185
179
186
180
for len (c .pending ) > 0 {
187
181
// pop the last entry off the pending list (we traverse the layers backwards)
188
- pending := c .pending [len (c .pending )- 1 ]
189
- files , err := pending .ref .FileList (ctx , s )
182
+ idx := len (c .pending ) - 1
183
+ pending := c .pending [idx ]
184
+ files , err := c .refs [idx ].FileList (ctx , s )
190
185
if err != nil {
191
- return nil , nil , err
186
+ return nil , err
192
187
}
193
188
c .pending = c .pending [:len (c .pending )- 1 ]
194
189
@@ -213,8 +208,18 @@ func (c *fileLayerFinder) find(ctx context.Context, s session.Group, filename st
213
208
}
214
209
}
215
210
if found {
216
- return pending .ref , & pending .desc , nil
211
+ return & pending , nil
212
+ }
213
+ }
214
+ return nil , fs .ErrNotExist
215
+ }
216
+
217
+ func (c * fileLayerFinder ) release (ctx context.Context ) error {
218
+ var err error
219
+ for _ , ref := range c .refs {
220
+ if err1 := ref .Release (ctx ); err1 != nil && err == nil {
221
+ err = err1
217
222
}
218
223
}
219
- return nil , nil , fs . ErrNotExist
224
+ return err
220
225
}
0 commit comments