@@ -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 {
@@ -344,27 +345,44 @@ func FilterManifestByPlatformHandler(f images.HandlerFunc, m platforms.Matcher)
344345
345346// annotateDistributionSourceHandler add distribution source label into
346347// annotation of config or blob descriptor.
347- func annotateDistributionSourceHandler (f images.HandlerFunc , manager content.Manager ) images.HandlerFunc {
348+ func annotateDistributionSourceHandler (f images.HandlerFunc , provider content.InfoProvider ) images.HandlerFunc {
348349 return func (ctx context.Context , desc ocispec.Descriptor ) ([]ocispec.Descriptor , error ) {
349350 children , err := f (ctx , desc )
350351 if err != nil {
351352 return nil , err
352353 }
353354
354- // only add distribution source for the config or blob data descriptor
355+ // Distribution source is only used for config or blob but may be inherited from
356+ // a manifest or manifest list
355357 switch desc .MediaType {
356358 case images .MediaTypeDockerSchema2Manifest , ocispec .MediaTypeImageManifest ,
357359 images .MediaTypeDockerSchema2ManifestList , ocispec .MediaTypeImageIndex :
358360 default :
359361 return children , nil
360362 }
361363
364+ // parentInfo can be used to inherit info for non-existent blobs
365+ var parentInfo * content.Info
366+
362367 for i := range children {
363368 child := children [i ]
364369
365- info , err := manager .Info (ctx , child .Digest )
370+ info , err := provider .Info (ctx , child .Digest )
366371 if err != nil {
367- return nil , err
372+ if ! errdefs .IsNotFound (err ) {
373+ return nil , err
374+ }
375+ if parentInfo == nil {
376+ pi , err := provider .Info (ctx , desc .Digest )
377+ if err != nil {
378+ return nil , err
379+ }
380+ parentInfo = & pi
381+ }
382+ // Blob may not exist locally, annotate with parent labels for cross repo
383+ // mount or fetch. Parent sources may apply to all children since most
384+ // registries enforce that children exist before the manifests.
385+ info = * parentInfo
368386 }
369387
370388 for k , v := range info .Labels {
0 commit comments