oras.land/oras-go/v2@v2.5.1-0.20240520045656-aef90e4d04c4/content/memory/memory.go (about) 1 /* 2 Copyright The ORAS Authors. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 // Package memory provides implementation of a memory backed content store. 17 package memory 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 24 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 25 "oras.land/oras-go/v2/content" 26 "oras.land/oras-go/v2/errdef" 27 "oras.land/oras-go/v2/internal/cas" 28 "oras.land/oras-go/v2/internal/graph" 29 "oras.land/oras-go/v2/internal/resolver" 30 ) 31 32 // Store represents a memory based store, which implements `oras.Target`. 33 type Store struct { 34 storage content.Storage 35 resolver content.TagResolver 36 graph *graph.Memory 37 } 38 39 // New creates a new memory based store. 40 func New() *Store { 41 return &Store{ 42 storage: cas.NewMemory(), 43 resolver: resolver.NewMemory(), 44 graph: graph.NewMemory(), 45 } 46 } 47 48 // Fetch fetches the content identified by the descriptor. 49 func (s *Store) Fetch(ctx context.Context, target ocispec.Descriptor) (io.ReadCloser, error) { 50 return s.storage.Fetch(ctx, target) 51 } 52 53 // Push pushes the content, matching the expected descriptor. 54 func (s *Store) Push(ctx context.Context, expected ocispec.Descriptor, reader io.Reader) error { 55 if err := s.storage.Push(ctx, expected, reader); err != nil { 56 return err 57 } 58 59 // index predecessors. 60 // there is no data consistency issue as long as deletion is not implemented 61 // for the memory store. 62 return s.graph.Index(ctx, s.storage, expected) 63 } 64 65 // Exists returns true if the described content exists. 66 func (s *Store) Exists(ctx context.Context, target ocispec.Descriptor) (bool, error) { 67 return s.storage.Exists(ctx, target) 68 } 69 70 // Resolve resolves a reference to a descriptor. 71 func (s *Store) Resolve(ctx context.Context, reference string) (ocispec.Descriptor, error) { 72 return s.resolver.Resolve(ctx, reference) 73 } 74 75 // Tag tags a descriptor with a reference string. 76 // Returns ErrNotFound if the tagged content does not exist. 77 func (s *Store) Tag(ctx context.Context, desc ocispec.Descriptor, reference string) error { 78 exists, err := s.storage.Exists(ctx, desc) 79 if err != nil { 80 return err 81 } 82 if !exists { 83 return fmt.Errorf("%s: %s: %w", desc.Digest, desc.MediaType, errdef.ErrNotFound) 84 } 85 return s.resolver.Tag(ctx, desc, reference) 86 } 87 88 // Predecessors returns the nodes directly pointing to the current node. 89 // Predecessors returns nil without error if the node does not exists in the 90 // store. 91 // Like other operations, calling Predecessors() is go-routine safe. However, 92 // it does not necessarily correspond to any consistent snapshot of the stored 93 // contents. 94 func (s *Store) Predecessors(ctx context.Context, node ocispec.Descriptor) ([]ocispec.Descriptor, error) { 95 return s.graph.Predecessors(ctx, node) 96 }