package cache import ( "errors" "fmt" v1 "github.com/google/go-containerregistry/pkg/v1" ) // cachingIndex wraps access to v1.ImageIndex with a [Cache]. Implements v1.ImageIndex type cachingIndex struct { wrappedIndex cache *LazyCache } // wrappedIndex lets us call index.wrappedIndex to delegate to the embedded // field's method without colliding with the interface func ImageIndex type wrappedIndex v1.ImageIndex // ImageIndex returns a new v1.ImageIndex backed by a cachingIndex. OCI interface methods will // read from the cache c, falling back to wrapped inner implementation if missing. Typically, the // inner Index will be a github.com/google/go-containerregistry/pkg/v1/remote/remoteIndex func ImageIndex(ii v1.ImageIndex, c *LazyCache) v1.ImageIndex { return &cachingIndex{ wrappedIndex: ii, cache: c, } } // Image returns a v1.Image that this ImageIndex references. func (c *cachingIndex) Image(h v1.Hash) (v1.Image, error) { if cached, err := c.cache.getImage(h); err == nil { return cached, nil } else if !errors.Is(err, ErrNotFound) { return nil, err } img, err := c.wrappedIndex.Image(h) if err != nil { return nil, fmt.Errorf("failed to get uncached Image: %v", err) } return c.cache.putImage(img) } // ImageIndex returns a v1.ImageIndex that this ImageIndex references. func (c *cachingIndex) ImageIndex(h v1.Hash) (v1.ImageIndex, error) { if cached, err := c.cache.getIndex(h); err == nil { return cached, nil } else if !errors.Is(err, ErrNotFound) { return nil, err } ii, err := c.wrappedIndex.ImageIndex(h) if err != nil { return nil, fmt.Errorf("failed to get uncached ImageIndex: %v", err) } return c.cache.putIndex(ii) }