@@ -24,11 +24,14 @@ import (
2424 "io"
2525 "path"
2626 "sort"
27+ "strings"
2728
2829 "github.com/containerd/containerd/v2/content"
2930 "github.com/containerd/containerd/v2/errdefs"
3031 "github.com/containerd/containerd/v2/images"
32+ "github.com/containerd/containerd/v2/labels"
3133 "github.com/containerd/containerd/v2/platforms"
34+ "github.com/containerd/log"
3235 digest "github.com/opencontainers/go-digest"
3336 ocispecs "github.com/opencontainers/image-spec/specs-go"
3437 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -191,6 +194,23 @@ func addNameAnnotation(name string, base map[string]string) map[string]string {
191194 return annotations
192195}
193196
197+ func copySourceLabels (ctx context.Context , infoProvider content.InfoProvider , desc ocispec.Descriptor ) (ocispec.Descriptor , error ) {
198+ info , err := infoProvider .Info (ctx , desc .Digest )
199+ if err != nil {
200+ return desc , err
201+ }
202+ for k , v := range info .Labels {
203+ if strings .HasPrefix (k , labels .LabelDistributionSource ) {
204+ if desc .Annotations == nil {
205+ desc .Annotations = map [string ]string {k : v }
206+ } else {
207+ desc .Annotations [k ] = v
208+ }
209+ }
210+ }
211+ return desc , nil
212+ }
213+
194214// ContentProvider provides both content and info about content
195215type ContentProvider interface {
196216 content.Provider
@@ -208,13 +228,22 @@ func Export(ctx context.Context, store ContentProvider, writer io.Writer, opts .
208228
209229 records := []tarRecord {
210230 ociLayoutFile ("" ),
211- ociIndexRecord (eo .manifests ),
231+ }
232+
233+ manifests := make ([]ocispec.Descriptor , 0 , len (eo .manifests ))
234+ for _ , desc := range eo .manifests {
235+ d , err := copySourceLabels (ctx , store , desc )
236+ if err != nil {
237+ log .G (ctx ).WithError (err ).WithField ("desc" , desc ).Warn ("failed to copy distribution.source labels" )
238+ continue
239+ }
240+ manifests = append (manifests , d )
212241 }
213242
214243 algorithms := map [string ]struct {}{}
215244 dManifests := map [digest.Digest ]* exportManifest {}
216245 resolvedIndex := map [digest.Digest ]digest.Digest {}
217- for _ , desc := range eo . manifests {
246+ for _ , desc := range manifests {
218247 if images .IsManifestType (desc .MediaType ) {
219248 mt , ok := dManifests [desc .Digest ]
220249 if ! ok {
@@ -304,6 +333,8 @@ func Export(ctx context.Context, store ContentProvider, writer io.Writer, opts .
304333 }
305334 }
306335
336+ records = append (records , ociIndexRecord (manifests ))
337+
307338 if ! eo .skipDockerManifest && len (dManifests ) > 0 {
308339 tr , err := manifestsRecord (ctx , store , dManifests )
309340 if err != nil {
0 commit comments