@@ -204,8 +204,9 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
204204// Base handlers can be provided which will be called before any push specific
205205// handlers.
206206//
207- // If the passed in content.Provider is also a content.Manager then this will
208- // also annotate the distribution sources in the manager.
207+ // If the passed in content.Provider is also a content.InfoProvider (such as
208+ // content.Manager) then this will also annotate the distribution sources using
209+ // labels prefixed with "containerd.io/distribution.source".
209210func PushContent (ctx context.Context , pusher Pusher , desc ocispec.Descriptor , store content.Provider , limiter * semaphore.Weighted , platform platforms.MatchComparer , wrapper func (h images.Handler ) images.Handler ) error {
210211
211212 var m sync.Mutex
@@ -234,7 +235,7 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
234235 platformFilterhandler := images .FilterPlatforms (images .ChildrenHandler (store ), platform )
235236
236237 var handler images.Handler
237- if m , ok := store .(content.Manager ); ok {
238+ if m , ok := store .(content.InfoProvider ); ok {
238239 annotateHandler := annotateDistributionSourceHandler (platformFilterhandler , m )
239240 handler = images .Handlers (annotateHandler , filterHandler , pushHandler )
240241 } else {
@@ -340,27 +341,44 @@ func FilterManifestByPlatformHandler(f images.HandlerFunc, m platforms.Matcher)
340341
341342// annotateDistributionSourceHandler add distribution source label into
342343// annotation of config or blob descriptor.
343- func annotateDistributionSourceHandler (f images.HandlerFunc , manager content.Manager ) images.HandlerFunc {
344+ func annotateDistributionSourceHandler (f images.HandlerFunc , provider content.InfoProvider ) images.HandlerFunc {
344345 return func (ctx context.Context , desc ocispec.Descriptor ) ([]ocispec.Descriptor , error ) {
345346 children , err := f (ctx , desc )
346347 if err != nil {
347348 return nil , err
348349 }
349350
350- // only add distribution source for the config or blob data descriptor
351+ // Distribution source is only used for config or blob but may be inherited from
352+ // a manifest or manifest list
351353 switch desc .MediaType {
352354 case images .MediaTypeDockerSchema2Manifest , ocispec .MediaTypeImageManifest ,
353355 images .MediaTypeDockerSchema2ManifestList , ocispec .MediaTypeImageIndex :
354356 default :
355357 return children , nil
356358 }
357359
360+ // parentInfo can be used to inherit info for non-existent blobs
361+ var parentInfo * content.Info
362+
358363 for i := range children {
359364 child := children [i ]
360365
361- info , err := manager .Info (ctx , child .Digest )
366+ info , err := provider .Info (ctx , child .Digest )
362367 if err != nil {
363- return nil , err
368+ if ! errdefs .IsNotFound (err ) {
369+ return nil , err
370+ }
371+ if parentInfo == nil {
372+ pi , err := provider .Info (ctx , desc .Digest )
373+ if err != nil {
374+ return nil , err
375+ }
376+ parentInfo = & pi
377+ }
378+ // Blob may not exist locally, annotate with parent labels for cross repo
379+ // mount or fetch. Parent sources may apply to all children since most
380+ // registries enforce that children exist before the manifests.
381+ info = * parentInfo
364382 }
365383
366384 for k , v := range info .Labels {
0 commit comments