@@ -198,8 +198,9 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
198198// Base handlers can be provided which will be called before any push specific
199199// handlers.
200200//
201- // If the passed in content.Provider is also a content.Manager then this will
202- // also annotate the distribution sources in the manager.
201+ // If the passed in content.Provider is also a content.InfoProvider (such as
202+ // content.Manager) then this will also annotate the distribution sources using
203+ // labels prefixed with "containerd.io/distribution.source".
203204func 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 {
204205
205206 var m sync.Mutex
@@ -223,7 +224,7 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
223224 platformFilterhandler := images .FilterPlatforms (images .ChildrenHandler (store ), platform )
224225
225226 var handler images.Handler
226- if m , ok := store .(content.Manager ); ok {
227+ if m , ok := store .(content.InfoProvider ); ok {
227228 annotateHandler := annotateDistributionSourceHandler (platformFilterhandler , m )
228229 handler = images .Handlers (annotateHandler , filterHandler , pushHandler )
229230 } else {
@@ -331,27 +332,44 @@ func FilterManifestByPlatformHandler(f images.HandlerFunc, m platforms.Matcher)
331332
332333// annotateDistributionSourceHandler add distribution source label into
333334// annotation of config or blob descriptor.
334- func annotateDistributionSourceHandler (f images.HandlerFunc , manager content.Manager ) images.HandlerFunc {
335+ func annotateDistributionSourceHandler (f images.HandlerFunc , provider content.InfoProvider ) images.HandlerFunc {
335336 return func (ctx context.Context , desc ocispec.Descriptor ) ([]ocispec.Descriptor , error ) {
336337 children , err := f (ctx , desc )
337338 if err != nil {
338339 return nil , err
339340 }
340341
341- // only add distribution source for the config or blob data descriptor
342+ // Distribution source is only used for config or blob but may be inherited from
343+ // a manifest or manifest list
342344 switch desc .MediaType {
343345 case images .MediaTypeDockerSchema2Manifest , ocispec .MediaTypeImageManifest ,
344346 images .MediaTypeDockerSchema2ManifestList , ocispec .MediaTypeImageIndex :
345347 default :
346348 return children , nil
347349 }
348350
351+ // parentInfo can be used to inherit info for non-existent blobs
352+ var parentInfo * content.Info
353+
349354 for i := range children {
350355 child := children [i ]
351356
352- info , err := manager .Info (ctx , child .Digest )
357+ info , err := provider .Info (ctx , child .Digest )
353358 if err != nil {
354- return nil , err
359+ if ! errdefs .IsNotFound (err ) {
360+ return nil , err
361+ }
362+ if parentInfo == nil {
363+ pi , err := provider .Info (ctx , desc .Digest )
364+ if err != nil {
365+ return nil , err
366+ }
367+ parentInfo = & pi
368+ }
369+ // Blob may not exist locally, annotate with parent labels for cross repo
370+ // mount or fetch. Parent sources may apply to all children since most
371+ // registries enforce that children exist before the manifests.
372+ info = * parentInfo
355373 }
356374
357375 for k , v := range info .Labels {
0 commit comments