@@ -39,6 +39,7 @@ type exportOptions struct {
3939 platform platforms.MatchComparer
4040 allPlatforms bool
4141 skipDockerManifest bool
42+ blobRecordOptions blobRecordOptions
4243}
4344
4445// ExportOpt defines options for configuring exported descriptors
@@ -108,6 +109,25 @@ func WithManifest(manifest ocispec.Descriptor, names ...string) ExportOpt {
108109 }
109110}
110111
112+ // BlobFilter returns false if the blob should not be included in the archive.
113+ type BlobFilter func (ocispec.Descriptor ) bool
114+
115+ // WithBlobFilter specifies BlobFilter.
116+ func WithBlobFilter (f BlobFilter ) ExportOpt {
117+ return func (ctx context.Context , o * exportOptions ) error {
118+ o .blobRecordOptions .blobFilter = f
119+ return nil
120+ }
121+ }
122+
123+ // WithSkipNonDistributableBlobs excludes non-distributable blobs such as Windows base layers.
124+ func WithSkipNonDistributableBlobs () ExportOpt {
125+ f := func (desc ocispec.Descriptor ) bool {
126+ return ! images .IsNonDistributable (desc .MediaType )
127+ }
128+ return WithBlobFilter (f )
129+ }
130+
111131func addNameAnnotation (name string , base map [string ]string ) map [string ]string {
112132 annotations := map [string ]string {}
113133 for k , v := range base {
@@ -143,7 +163,7 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
143163 mt , ok := dManifests [desc .Digest ]
144164 if ! ok {
145165 // TODO(containerd): Skip if already added
146- r , err := getRecords (ctx , store , desc , algorithms )
166+ r , err := getRecords (ctx , store , desc , algorithms , & eo . blobRecordOptions )
147167 if err != nil {
148168 return err
149169 }
@@ -162,7 +182,7 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
162182 case images .MediaTypeDockerSchema2ManifestList , ocispec .MediaTypeImageIndex :
163183 d , ok := resolvedIndex [desc .Digest ]
164184 if ! ok {
165- records = append (records , blobRecord (store , desc ))
185+ records = append (records , blobRecord (store , desc , & eo . blobRecordOptions ))
166186
167187 p , err := content .ReadBlob (ctx , store , desc )
168188 if err != nil {
@@ -184,7 +204,7 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
184204 }
185205 }
186206
187- r , err := getRecords (ctx , store , m , algorithms )
207+ r , err := getRecords (ctx , store , m , algorithms , & eo . blobRecordOptions )
188208 if err != nil {
189209 return err
190210 }
@@ -248,10 +268,10 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
248268 return writeTar (ctx , tw , records )
249269}
250270
251- func getRecords (ctx context.Context , store content.Provider , desc ocispec.Descriptor , algorithms map [string ]struct {}) ([]tarRecord , error ) {
271+ func getRecords (ctx context.Context , store content.Provider , desc ocispec.Descriptor , algorithms map [string ]struct {}, brOpts * blobRecordOptions ) ([]tarRecord , error ) {
252272 var records []tarRecord
253273 exportHandler := func (ctx context.Context , desc ocispec.Descriptor ) ([]ocispec.Descriptor , error ) {
254- records = append (records , blobRecord (store , desc ))
274+ records = append (records , blobRecord (store , desc , brOpts ))
255275 algorithms [desc .Digest .Algorithm ().String ()] = struct {}{}
256276 return nil , nil
257277 }
@@ -277,7 +297,14 @@ type tarRecord struct {
277297 CopyTo func (context.Context , io.Writer ) (int64 , error )
278298}
279299
280- func blobRecord (cs content.Provider , desc ocispec.Descriptor ) tarRecord {
300+ type blobRecordOptions struct {
301+ blobFilter BlobFilter
302+ }
303+
304+ func blobRecord (cs content.Provider , desc ocispec.Descriptor , opts * blobRecordOptions ) tarRecord {
305+ if opts != nil && opts .blobFilter != nil && ! opts .blobFilter (desc ) {
306+ return tarRecord {}
307+ }
281308 path := path .Join ("blobs" , desc .Digest .Algorithm ().String (), desc .Digest .Encoded ())
282309 return tarRecord {
283310 Header : & tar.Header {
@@ -438,7 +465,13 @@ func manifestsRecord(ctx context.Context, store content.Provider, manifests map[
438465 }, nil
439466}
440467
441- func writeTar (ctx context.Context , tw * tar.Writer , records []tarRecord ) error {
468+ func writeTar (ctx context.Context , tw * tar.Writer , recordsWithEmpty []tarRecord ) error {
469+ var records []tarRecord
470+ for _ , r := range recordsWithEmpty {
471+ if r .Header != nil {
472+ records = append (records , r )
473+ }
474+ }
442475 sort .Slice (records , func (i , j int ) bool {
443476 return records [i ].Header .Name < records [j ].Header .Name
444477 })
0 commit comments