package disk import ( "fmt" "os" "path" "path/filepath" "sync" "github.com/google/go-containerregistry/pkg/name" "edge-infra.dev/pkg/f8n/warehouse/oci" "edge-infra.dev/pkg/f8n/warehouse/oci/layout" ) // Cache is a thread-safe wrapper around an OCI Image Layout with functionality // for purging. type Cache struct { sync.RWMutex path *layout.Path } // New returns a new instance of the disk Cache. func New(layoutPath *layout.Path) *Cache { return &Cache{path: layoutPath} } // FromPath returns a new instance of the disk Cache from an existing path. func FromPath(path string) (*Cache, error) { layoutPath, err := layout.New(path) if err != nil { return nil, err } return &Cache{path: layoutPath}, nil } // Get fetches an oci artifact from an oci layout path. func (d *Cache) Get(ref name.Reference) (oci.Artifact, error) { d.RLock() defer d.RUnlock() a, err := d.path.Get(ref) if err != nil { return nil, err } return a, nil } // Exists check if an oci artifact exists in the oci layout path. func (d *Cache) Exists(ref name.Reference) bool { // TODO(aw18576): not needed because we will lock in Get? // d.RLock() // defer d.RUnlock() _, err := d.path.Get(ref) return err == nil } // Add appends an oci artifact to a layout path. func (d *Cache) Add(ref name.Reference, a oci.Artifact) error { d.Lock() defer d.Unlock() return d.path.Append(ref, a) } // Purge deletes an oci layout path from disk. func (d *Cache) Purge() error { layoutPath := string(d.path.Path) contents, err := filepath.Glob(path.Join(layoutPath, "/*")) if err != nil { return err } for _, item := range contents { err = os.RemoveAll(item) if err != nil { return err } } np, err := layout.New(layoutPath) if err != nil { return fmt.Errorf("failed to re-instantiate empty layout: %w", err) } d.path = np return nil }